package com.keur.money.utils.event;

import android.content.Context;

import androidx.annotation.NonNull;

import com.keur.money.base.utils.log.MullaLog;
import com.keur.money.http.ApiService;
import com.keur.money.http.HttpHelper;
import com.keur.money.http.IHttpCallback;
import com.keur.money.utils.room.UserBehaviorDatabase;
import com.keur.money.utils.room.UserEvent;
import com.keur.money.utils.room.UserEventDao;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * MullaFlow
 * @Author wwdeng
 * @CreateTime: 2025/5/30 14:15
 * @Annotation： 用户使用埋点收集与上报
 */
public class KeurBehaviorTracker {

    private static final long DEFAULT_REPORT_INTERVAL = 60 * 60 * 1000; // 默认60分钟上报一次
    private static final long DEFAULT_CLEANUP_INTERVAL = 30 * 60 * 1000; // 默认30分钟清理一次

    private static volatile KeurBehaviorTracker instance;
    private final UserEventDao eventDao;
    private final ExecutorService ioExecutor;
    private final ScheduledExecutorService scheduler;

    public interface ReportCallback {
        void onSuccess();
        void onFailure(String error);
    }

    private KeurBehaviorTracker(Context context) {
        UserBehaviorDatabase db = UserBehaviorDatabase.getDatabase(context.getApplicationContext());
        eventDao = db.eventDao();
        ioExecutor = Executors.newSingleThreadExecutor();
        scheduler = Executors.newSingleThreadScheduledExecutor();
        initScheduledTasks();
    }

    public static KeurBehaviorTracker getInstance(Context context) {
        if (instance == null) {
            synchronized (KeurBehaviorTracker.class) {
                if (instance == null) {
                    instance = new KeurBehaviorTracker(context);
                }
            }
        }
        return instance;
    }

    /**
     * 记录用户行为事件
     * @param eventType 事件类型
     * @param remark 事件备注
     */
    public void trackEvent(@NonNull String eventType, @NonNull String remark) {
        ioExecutor.execute(() -> {
            UserEvent event = new UserEvent(eventType, remark, System.currentTimeMillis(), false);
            eventDao.insert(event);
        });
    }

    /**
     * 立即上报未上报的事件
     * @param callback 上报结果回调
     */
    public void reportImmediately(ReportCallback callback) {
        ioExecutor.execute(() -> {
            List<UserEvent> unreportedEvents = eventDao.getUnreportedEvents();
            if (unreportedEvents.isEmpty() && callback != null) {
                callback.onSuccess();
                return;
            }
            performReport(unreportedEvents,callback);
        });
    }

    /**
     * 启动定时上报
     * @param interval 上报间隔（毫秒），0表示使用默认间隔
     */
    public void startScheduledReporting(long interval) {
        long reportInterval = interval > 0 ? interval : DEFAULT_REPORT_INTERVAL;
        scheduler.scheduleAtFixedRate(() -> reportImmediately(new SimpleReportCallback()),
                reportInterval, reportInterval, TimeUnit.MILLISECONDS);
    }

    /**
     * 清理已上报的事件
     */
    public void cleanupReportedEvents() {
        ioExecutor.execute(eventDao::deleteReportedEvents);
    }

    /**
     * 释放资源
     */
    public void release() {
        scheduler.shutdown();
        ioExecutor.shutdown();
    }

    private void initScheduledTasks() {
        startScheduledReporting(0);
        scheduler.scheduleAtFixedRate(this::cleanupReportedEvents,
                DEFAULT_CLEANUP_INTERVAL, DEFAULT_CLEANUP_INTERVAL, TimeUnit.MILLISECONDS);
    }

    /**
     * 上报所有事件
     * @param events：所有事件列表
     * @param callback：上报事件回调
     */
    private void performReport(List<UserEvent> events,ReportCallback callback) {
        if (events.isEmpty()){
            if (callback != null){
                callback.onSuccess();
            }
            return;
        }
        //上报
        JSONObject params = new JSONObject();
        try {
            JSONArray array = new JSONArray();
            for (UserEvent event : events){
                MullaLog.e("track event >>> id="+event.getId()+">>>type="+event.getType()+">>>remark="+event.getRemark()+">>>timestamp="+event.getTimestamp()+">>>isReported="+event.isReported());
                JSONObject obj = new JSONObject();
                obj.put("id",event.getId());
                obj.put("type",event.getType());
                obj.put("remark",event.getRemark());
                obj.put("timestamp",event.getTimestamp());
                array.put(obj);
            }
            params.put("list",array);
        } catch (JSONException e) {
            MullaLog.e("track params format failed!");
        }
        String httpUrl = ApiService.INSTANCE.getHttpUrl(ApiService.API_PATH.KEUR_API_TRACK_EVENT_BATCH_PATH);
        HttpHelper.INSTANCE.postKeurEventAction(httpUrl, params, new IHttpCallback() {
            @Override
            public void onRequestSuccess(@NonNull JSONObject data) {
                int code = data.optInt("code");
                if (code == 0){
                    //更新事件状态为已上报
                    markEventsAsReported(events);
                    if (callback != null){
                        callback.onSuccess();
                    }
                } else {
                    if (callback != null){
                        callback.onFailure("track update failed!");
                    }
                }
            }
            @Override
            public void onRequestError(@NonNull JSONObject error) {
            }
            @Override
            public void onRequestFinish() {
            }
        });
    }

    /**
     * 更新事件状态
     * @param events：所有事件列表
     */
    private void markEventsAsReported(List<UserEvent> events) {
        ioExecutor.execute(() -> {
            for (UserEvent event : events) {
                event.setReported(true);
            }
            eventDao.updateEvents(events);
        });
    }

    private static class SimpleReportCallback implements ReportCallback {
        @Override
        public void onSuccess() {
        }

        @Override
        public void onFailure(String error) {
        }
    }
}
